#pragma once

#include "../../plugin/base/entity.hh"
#include "lua_helper.hh"

// Entity in Lua VM
class LuaEntity : public AddressEntity {
    bool luaDisposed_; // Call dispose method in Lua will set it true
    std::string metaKey_; // The key of metatable

public:
    // CTOR
    LuaEntity();
    // DTOR
    virtual ~LuaEntity() {}
    // Useless method
    static EntityType staticType() { return 0; }
    // Call RPC method in Lua VM
    // @param pathID The path on locator
    // @param fromPathID The path on source node
    // @param UUID RPC UUID
    // @param RPCID RPC method ID
    // @param interface The name of interface
    // @param method The method name of interface
    // @param req The request message
    // @param ack The response message for instant return
    bool callLuaImplMethod(
        PathID pathID,
        PathID fromPathID, 
        std::uint64_t UUID,
        std::uint64_t RPCID,
        const char* interface,
        const char* method,
        const google::protobuf::Message& req,
        google::protobuf::Message& ack
    );

private:
    // Remove metatable of entity
    void removeMetatable(lua_State* L);
    // Check lua dispose flag
    bool isLuaDisposed();
    // Dispose entity in Lua VM
    void luaDispose();
    // Push entity's metatable onto stack
    void pushMetatable(lua_State* L);
    // Add attribute to entity
    void addAttribute(lua_State* L);

public:
    // Install entity library
    static void installEntityLibrary(lua_State * L);

public:
    // The metamethod for new entity
    static int newLuaEntity(lua_State* L);
    // The metamethod for __gc
    static int deleteLuaEntity(lua_State* L);
    // The metamethod for resolve entity
    static int luaResolve(lua_State* L);
    // The metamethod for __newindex
    static int luaAssign(lua_State* L);
    // The metamethod for dispose entity in Lua VM
    static int luaDispose(lua_State* L);
};
